using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using System.Xml;
using ICSharpCode.TextEditor.Document;

namespace ICSharpCode.TextEditor.Src.Document.FoldingStrategy
{
	public class XmlFoldingStrategy : IFoldingStrategyEx, IFoldingStrategy
	{
		public bool ShowAttributesWhenFolded = false;

		private List<string> _foldingErrors = new List<string>();

		public List<string> GetFoldingErrors()
		{
			return this._foldingErrors;
		}

		public List<FoldMarker> GenerateFoldMarkers(IDocument document, string fileName, object parseInformation)
		{
			this._foldingErrors = new List<string>();
			List<FoldMarker> list = new List<FoldMarker>();
			Stack stack = new Stack();
			try
			{
				string textContent = document.TextContent;
				XmlTextReader xmlTextReader = new XmlTextReader(new StringReader(textContent));
				while (xmlTextReader.Read())
				{
					switch (xmlTextReader.NodeType)
					{
					case XmlNodeType.Element:
						if (!xmlTextReader.IsEmptyElement)
						{
							XmlFoldStart obj = this.CreateElementFoldStart(xmlTextReader);
							stack.Push(obj);
						}
						break;
					case XmlNodeType.EndElement:
					{
						XmlFoldStart foldStart = (XmlFoldStart)stack.Pop();
						this.CreateElementFold(document, list, xmlTextReader, foldStart);
						break;
					}
					case XmlNodeType.Comment:
						this.CreateCommentFold(document, list, xmlTextReader);
						break;
					}
				}
			}
			catch (Exception ex)
			{
				this._foldingErrors.Add(ex.Message);
				return new List<FoldMarker>(document.FoldingManager.FoldMarker);
			}
			return list;
		}

		private static string XmlEncodeAttributeValue(string attributeValue, char quoteChar)
		{
			StringBuilder stringBuilder = new StringBuilder(attributeValue);
			stringBuilder.Replace("&", "&amp;");
			stringBuilder.Replace("<", "&lt;");
			stringBuilder.Replace(">", "&gt;");
			if (quoteChar == '"')
			{
				stringBuilder.Replace("\"", "&quot;");
			}
			else
			{
				stringBuilder.Replace("'", "&apos;");
			}
			return stringBuilder.ToString();
		}

		private void CreateCommentFold(IDocument document, List<FoldMarker> foldMarkers, XmlTextReader reader)
		{
			if (reader.Value != null)
			{
				string text = reader.Value.Replace("\r\n", "\n");
				string[] array = text.Split('\n');
				if (array.Length > 1)
				{
					int num = reader.LinePosition - 5;
					int num2 = reader.LineNumber - 1;
					int endColumn = array[^1].Length + num + 3;
					int endLine = num2 + array.Length - 1;
					string foldText = "<!--" + array[0] + "-->";
					FoldMarker item = new FoldMarker(document, num2, num, endLine, endColumn, FoldType.TypeBody, foldText);
					foldMarkers.Add(item);
				}
			}
		}

		private void CreateElementFold(IDocument document, List<FoldMarker> foldMarkers, XmlTextReader reader, XmlFoldStart foldStart)
		{
			int num = reader.LineNumber - 1;
			if (num > foldStart.Line)
			{
				int endColumn = reader.LinePosition + foldStart.Name.Length;
				FoldMarker item = new FoldMarker(document, foldStart.Line, foldStart.Column, num, endColumn, FoldType.TypeBody, foldStart.FoldText);
				foldMarkers.Add(item);
			}
		}

		private XmlFoldStart CreateElementFoldStart(XmlTextReader reader)
		{
			XmlFoldStart xmlFoldStart = new XmlFoldStart(reader.Prefix, reader.LocalName, reader.LineNumber - 1, reader.LinePosition - 2);
			if (this.ShowAttributesWhenFolded && reader.HasAttributes)
			{
				xmlFoldStart.FoldText = "<" + xmlFoldStart.Name + " " + this.GetAttributeFoldText(reader) + ">";
			}
			else
			{
				xmlFoldStart.FoldText = "<" + xmlFoldStart.Name + ">";
			}
			return xmlFoldStart;
		}

		private string GetAttributeFoldText(XmlTextReader reader)
		{
			StringBuilder stringBuilder = new StringBuilder();
			for (int i = 0; i < reader.AttributeCount; i++)
			{
				reader.MoveToAttribute(i);
				stringBuilder.Append(reader.Name);
				stringBuilder.Append("=");
				stringBuilder.Append(reader.QuoteChar.ToString(CultureInfo.InvariantCulture));
				stringBuilder.Append(XmlFoldingStrategy.XmlEncodeAttributeValue(reader.Value, reader.QuoteChar));
				stringBuilder.Append(reader.QuoteChar.ToString(CultureInfo.InvariantCulture));
				if (i < reader.AttributeCount - 1)
				{
					stringBuilder.Append(" ");
				}
			}
			return stringBuilder.ToString();
		}
	}
}
